package mqttlib

import (
	"MqttCloudProtocolServer/publiclib/datamodel"
	"MqttCloudProtocolServer/publiclib/datamodel/dborm"
	"strconv"
	"strings"
	"sync"
	"time"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/google/uuid"
	"github.com/wonderivan/logger"
)

//MqttConnectionDef MQTT连接共用，单独起一个类
type MqttConnectionDef struct {
	OperatorBase
	mqttGlobalClient mqtt.Client
	//mqttGlobalServerData   *datamodel.MqttServer
	mqttGlobaldbServerData *dborm.Mqttserver
	cmd                    chan string
	isClosed               bool
	mqttCSPares            map[string]*MqttCSPareClass
}

//Start 初始化总MQTT服务
func (_this *MqttConnectionDef) Start() bool {
	addr := "tcp://" + _this.mqttGlobaldbServerData.Host + ":" + strconv.Itoa(_this.mqttGlobaldbServerData.Port)

	for _, pare := range _this.mqttCSPares {
		pare.InitTopic()
	}

	//connect mqtt-server and set clientID
	opts := mqtt.NewClientOptions().AddBroker(addr).SetClientID(_this.GetKey() + strings.Replace(uuid.NewString(), "-", "", -1))

	//set userName
	opts.SetUsername(_this.mqttGlobaldbServerData.User)
	opts.SetPassword(_this.mqttGlobaldbServerData.Password)
	opts.SetKeepAlive(2 * time.Second)
	opts.SetPingTimeout(1 * time.Second)
	opts.SetConnectRetryInterval(time.Second * 1)
	opts.SetConnectRetry(true)
	opts.SetAutoReconnect(true)
	opts.SetMaxReconnectInterval(time.Second * 1)
	opts.SetOnConnectHandler(func(cc mqtt.Client) {
		logger.Debug(_this.key + ": Connect")
		_this.mqttGlobalClient = cc
		//subscribe topic
		for _, pare := range _this.mqttCSPares {
			pare.SetMqttClient(cc)
			pare.SubMessage()
		}
	})
	opts.SetConnectionLostHandler(func(_ mqtt.Client, _ error) {
		_this.mqttGlobalClient = nil
		for _, pare := range _this.mqttCSPares {
			pare.SetMqttClient(nil)
		}
		logger.Debug(_this.key + ": LostConnect")
	})

	opts.SetReconnectingHandler(func(_ mqtt.Client, _ *mqtt.ClientOptions) {
		logger.Debug(_this.key + ": ReConnect")
	})
	//create object
	c := mqtt.NewClient(opts)
	c.Connect()
	res := <-_this.cmd
	if res == "Close" {
		return true
	}
	return false

}

//Modify Fun
func (_this *MqttConnectionDef) Modify(params interface{}) bool {
	switch params.(type) {
	case *datamodel.MqttServer:
		//_this.mqttGlobalServerData = params.(*datamodel.MqttServer)
		break
	case *dborm.Mqttserver:
		_this.mqttGlobaldbServerData = params.(*dborm.Mqttserver)
		break
	case map[string]*MqttCSPareClass:
		_this.mqttCSPares = params.(map[string]*MqttCSPareClass)
	default:
		return false
	}
	return true
}

//Close Fun
func (_this *MqttConnectionDef) Close() bool {
	if _this.mqttGlobalClient != nil && _this.mqttGlobalClient.IsConnected() {
		var muxLock sync.WaitGroup
		for _, pare := range _this.mqttCSPares {
			muxLock.Add(1)
			go func(e *MqttCSPareClass, lock *sync.WaitGroup) {
				e.Close()
				lock.Done()
			}(pare, &muxLock)
			muxLock.Wait()
		}
		_this.mqttCSPares = make(map[string]*MqttCSPareClass)
		_this.mqttGlobalClient.Disconnect(250)
	}
	return true
}

//SendData 发送数据
func (_this *MqttConnectionDef) SendData(key string, buffer []uint8) {
	if val, ok := _this.mqttCSPares[key]; ok {
		val.SendData(buffer)
	} else {
		logger.Warn("TCP:" + key + "不存在或已删除")
	}
}
